﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using CommonBasic = DevelopStudio.Common.Basic;
using CommonManage = DevelopStudio.Common.Manage;
using SNSHelper.Common;
using DevelopStudio.Basic;
using System.IO;
using System.Reflection;
using System.Globalization;

namespace DevelopStudio.Basic
{
    [Serializable]
    [XmlRoot("issue")]
    public class BugInfo : ICloneable
    {
        public BugInfo()
        {
            Init();
        }

        private void Init()
        {
        }

        [XmlElement("id")]
        public int ID { get; set; }

        [XmlElement("project")]
        public IdNamePair Project { get; set; }

        [XmlElement("tracker")]
        public IdNamePair Tracker { get; set; }

        [XmlElement("status")]
        public IdNamePair Status { get; set; }

        [XmlElement("priority")]
        public IdNamePair Priority { get; set; }

        [XmlElement("author")]
        public IdNamePair Author { get; set; }

        [XmlElement("assigned_to")]
        public IdNamePair AssignedTo { get; set; }

        [XmlElement("category")]
        public IdNamePair Category { get; set; }

        [XmlElement("fixed_version")]
        public IdNamePair FixedVersion { get; set; }

        [XmlElement("subject")]
        public string Subject { get; set; }

        [XmlElement("description")]
        public string Description { get; set; }

        [XmlElement("start_date")]
        public string StartDate { get; set; }

        [XmlElement("due_date")]
        public string DueDate { get; set; }

        [XmlElement("done_ratio")]
        public string DoneRation { get; set; }

        [XmlElement("estimated_hours")]
        public string EstimatedHours { get; set; }

        [XmlElement("spent_hours")]
        public string SpentHours { get; set; }

        [XmlArray("custom_fields")]
        [XmlArrayItem("custom_field")]
        public List<IdNamePair> CustomFields { get; set; }

        [XmlElement("created_on")]
        public string CreatedOn { get; set; }

        [XmlElement("updated_on")]
        public string UpdatedOn { get; set; }

        [XmlIgnore]
        public AppEnum.BugAssignedStatus AssignedStatus { get; set; }

        [XmlIgnore]
        public string ActionStatus { get; set; }

        public object Clone()
        {
            MemoryStream stream = new MemoryStream();

            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(BugInfo));
                serializer.Serialize(stream, this);
                stream.Flush();
                stream.Position = 0;
                BugInfo newObject = serializer.Deserialize(stream) as BugInfo;
                return newObject;
            }
            finally
            {
                stream.Dispose();
            }
        }

        private string ReadyCodeReviewData(ChangelistInfo changelistInfo, AppEnum.ChangelistStatus newChangelistStatus)
        {
            IdNamePair reviewStatus = this.CustomFields.Find(o => o.ID == "33");
            IdNamePair reviewContent = this.CustomFields.Find(o => o.ID == "32");
            IdNamePair reviewReviewer = this.CustomFields.Find(o => o.ID == "31");
            SortedList statusMap = AppEnum.GetCodeReviewStatus();

            WorkingCopyInfo copyInfo = Utility.Settings.WorkingCopies.Find(o => o.Path ==  changelistInfo.WorkingCopyPath);

            switch (newChangelistStatus)
            {
                case AppEnum.ChangelistStatus.SendReviewing:
                    {
                        reviewStatus.Value = AppEnum.GetDescription(typeof(AppEnum.BugCodeReviewStatus), AppEnum.BugCodeReviewStatus.Reviewing);
                        reviewReviewer.Value = this.AssignedTo.ID;
                        //评审内容的结构为发起者, 绑定的changelist Name, Path, Comment
                        reviewContent.Value = string.Format(CultureInfo.CurrentCulture, Properties.Resources.CodeReviewFormat, Utility.Settings.MyInfo.ID, changelistInfo.Name, copyInfo.Url, changelistInfo.StoredPath, Properties.Resources.SendCodeReviewComment, changelistInfo.Comment, Environment.NewLine, Utility.Settings.MyInfo.Name, (int)newChangelistStatus);
                    }
                    break;
                case AppEnum.ChangelistStatus.CanceledReview:
                    {
                        reviewStatus.Value = AppEnum.GetDescription(typeof(AppEnum.BugCodeReviewStatus), AppEnum.BugCodeReviewStatus.None);
                        reviewReviewer.Value = string.Empty;
                        //评审内容的结构为发起者, 绑定的changelist Name, Path, Comment
                        reviewContent.Value = string.Format(CultureInfo.CurrentCulture, Properties.Resources.CodeReviewFormat, Utility.Settings.MyInfo.ID, changelistInfo.Name, copyInfo.Url, string.Empty, Properties.Resources.CanceledCodeReviewComment, string.Empty, Environment.NewLine, Utility.Settings.MyInfo.Name, (int)newChangelistStatus);
                    }
                    break;
                case AppEnum.ChangelistStatus.Approved:
                    {
                        reviewStatus.Value = AppEnum.GetDescription(typeof(AppEnum.BugCodeReviewStatus), AppEnum.BugCodeReviewStatus.Approved);
                        reviewReviewer.Value = Utility.Settings.MyInfo.ID;
                        //评审内容的结构为发起者, 绑定的changelist Name, Path, Comment
                        reviewContent.Value = string.Format(CultureInfo.CurrentCulture, Properties.Resources.CodeReviewFormat, Utility.Settings.MyInfo.ID, changelistInfo.Name, changelistInfo.WorkingCopyPath, changelistInfo.StoredPath, Properties.Resources.ApprovedCodeReview, string.Empty, Environment.NewLine, Utility.Settings.MyInfo.Name, (int)newChangelistStatus);
                    }
                    break;
                case AppEnum.ChangelistStatus.ApprovedWithComment:
                    {
                        reviewStatus.Value = AppEnum.GetDescription(typeof(AppEnum.BugCodeReviewStatus), AppEnum.BugCodeReviewStatus.Approved);
                        reviewReviewer.Value = Utility.Settings.MyInfo.ID;
                        //评审内容的结构为发起者, 绑定的changelist Name, Path, Comment
                        reviewContent.Value = string.Format(CultureInfo.CurrentCulture, Properties.Resources.CodeReviewFormat, Utility.Settings.MyInfo.ID, changelistInfo.Name, changelistInfo.WorkingCopyPath, changelistInfo.StoredPath, Properties.Resources.ApprovedCodeReviewWithComment, changelistInfo.FeedbackComment, Environment.NewLine, Utility.Settings.MyInfo.Name, (int)newChangelistStatus);
                    }
                    break;
                case AppEnum.ChangelistStatus.Rejected:
                    {
                        reviewStatus.Value = AppEnum.GetDescription(typeof(AppEnum.BugCodeReviewStatus), AppEnum.BugCodeReviewStatus.Rejected);
                        reviewReviewer.Value = Utility.Settings.MyInfo.ID;
                        //评审内容的结构为发起者, 绑定的changelist Name, Path, Comment
                        reviewContent.Value = string.Format(CultureInfo.CurrentCulture, Properties.Resources.CodeReviewFormat, Utility.Settings.MyInfo.ID, changelistInfo.Name, changelistInfo.WorkingCopyPath, changelistInfo.StoredPath, Properties.Resources.RejectedCodeReviewComment, changelistInfo.FeedbackComment, Environment.NewLine, Utility.Settings.MyInfo.Name, (int)newChangelistStatus);
                    }
                    break;
                case AppEnum.ChangelistStatus.CommitedButWaiting:
                    {
                        //评审内容的结构为发起者, 绑定的changelist Name, Path, Comment
                        reviewContent.Value = string.Format(CultureInfo.CurrentCulture, Properties.Resources.CodeReviewFormat, Utility.Settings.MyInfo.ID, changelistInfo.Name, changelistInfo.WorkingCopyPath, changelistInfo.StoredPath, string.Format(Properties.Resources.CommitComment, changelistInfo.Name, copyInfo.Url), changelistInfo.Comment, Environment.NewLine, Utility.Settings.MyInfo.Name, (int)newChangelistStatus);
                    }
                    break;
                case AppEnum.ChangelistStatus.Local:
                    {
                        if (AssignedStatus == AppEnum.BugAssignedStatus.Removed)
                        {
                            reviewStatus.Value = AppEnum.GetDescription(typeof(AppEnum.BugCodeReviewStatus), AppEnum.BugCodeReviewStatus.None);
                            reviewReviewer.Value = string.Empty;
                            //评审内容的结构为发起者, 绑定的changelist Name, Path, Comment
                            reviewContent.Value = string.Empty;

                            return string.Format(Properties.Resources.UnAssignBugsComment, changelistInfo.Name, Environment.MachineName);

                        }
                        else if (AssignedStatus == AppEnum.BugAssignedStatus.NewAdded)
                        {
                            reviewStatus.Value = AppEnum.GetDescription(typeof(AppEnum.BugCodeReviewStatus), AppEnum.BugCodeReviewStatus.None);
                            reviewReviewer.Value = string.Empty;
                            //评审内容的结构为发起者, 绑定的changelist Name, Path, Comment
                            reviewContent.Value = string.Format(CultureInfo.CurrentCulture, Properties.Resources.CodeReviewFormat, Utility.Settings.MyInfo.ID, changelistInfo.Name, copyInfo.Url, string.Empty, string.Format(Properties.Resources.AssignBugsComment, changelistInfo.Name, Environment.MachineName), changelistInfo.Comment, Environment.NewLine, Utility.Settings.MyInfo.Name, (int)newChangelistStatus);
                        }
                        else
                        {
                            return string.Empty;
                        }
                    }
                    break;
                default:
                    break;
            }

            return reviewContent.Value;
        }

        public bool UpdateRedmine(ChangelistInfo changelistInfo, AppEnum.ChangelistStatus newChangelistStatus)
        {
            try
            {
                if (newChangelistStatus == AppEnum.ChangelistStatus.Disabled)
                {
                    return false;
                }

                if (newChangelistStatus == AppEnum.ChangelistStatus.Local  &&
                    this.AssignedStatus == AppEnum.BugAssignedStatus.Added)
                {
                    return false;
                }

                string bugPageUrl = Utility.GetAbsoluteUrl(string.Format(AppConst.BugsPageUrl, this.ID));
                string bugPageEditUrl = Utility.GetAbsoluteUrl(string.Format(AppConst.BugsPageEditUrl, this.ID));

                string editHtml = Utility.GetHtml(bugPageEditUrl);

                int index = 0;
                string authenticityToken = Utility.GetMidString(editHtml, "<input name=\"authenticity_token\" type=\"hidden\" value=\"", "\"", ref index);

                if (index == -1)
                {
                    return false;
                }

                string lockVersion = Utility.GetMidString(editHtml, "<input id=\"issue_lock_version\" name=\"issue[lock_version]\" type=\"hidden\" value=\"", "\"", ref index);

                if (index == -1)
                {
                    return false;
                }

                Dictionary<string, string> formData = new Dictionary<string, string>();

                formData.Add("_method", "put");
                formData.Add("authenticity_token", authenticityToken);

                if (this.Tracker != null)
                    formData.Add("issue[tracker_id]", this.Tracker.ID);

                formData.Add("issue[subject]", this.Subject);
                formData.Add("issue[description]", this.Description);

                if (this.Status != null)
                    formData.Add("issue[status_id]", this.Status.ID);

                if (this.Priority != null)
                    formData.Add("issue[priority_id]", this.Priority.ID);

                if (this.AssignedTo != null)
                    formData.Add("issue[assigned_to_id]", this.AssignedTo.ID);

                if (this.Category != null)
                    formData.Add("issue[category_id]", this.Category.ID);

                if (this.FixedVersion != null)
                    formData.Add("issue[fixed_version_id]", this.FixedVersion.ID);
                else
                    formData.Add("issue[fixed_version_id]", string.Empty);

                formData.Add("issue[start_date]", this.StartDate);
                formData.Add("issue[due_date]", this.DueDate);
                formData.Add("issue[estimated_hours]", this.EstimatedHours);

                string comment = this.ReadyCodeReviewData(changelistInfo, newChangelistStatus);

                foreach (IdNamePair var in this.CustomFields)
                {
                    formData.Add(string.Format("issue[custom_field_values][{0}]", var.ID), var.Value);
                }

                formData.Add("time_entry[hours]", string.Empty);
                formData.Add("time_entry[activity_id]", "12");
                formData.Add("time_entry[comments]", string.Empty);

                if (string.IsNullOrEmpty(comment) == false)
                {
                    formData.Add("notes", comment);
                }

                formData.Add("attachments[1][file]", string.Empty);
                formData.Add("attachments[1][description]", string.Empty);
                formData.Add("issue[lock_version]", lockVersion);
                formData.Add("commit", "提交");

                string html = Utility.HttpHelper.HttpPostFormData(bugPageUrl, bugPageEditUrl, formData/*, "attachments[1][file]"*/);

                if (html.Contains("redirected") == true)
                {
                    return true;
                }
            }
            catch (Exception)
            {
                return false;
            }

            return false;
        }
    }
}
